home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char Rcs_Id[] =
- "$Id: term.c,v 1.48 1994/10/25 05:46:11 geoff Exp $";
- #endif
-
- /*
- * term.c - deal with termcap, and unix terminal mode settings
- *
- * Pace Willisson, 1983
- *
- * Copyright 1987, 1988, 1989, 1992, 1993, Geoff Kuenning, Granada Hills, CA
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All modifications to the source code must be clearly marked as
- * such. Binary redistributions based on modified source code
- * must be clearly marked as modified versions in the documentation
- * and/or other materials provided with the distribution.
- * 4. All advertising materials mentioning features or use of this software
- * must display the following acknowledgment:
- * This product includes software developed by Geoff Kuenning and
- * other unpaid contributors.
- * 5. The name of Geoff Kuenning may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
- /*
- * $Log: term.c,v $
- * Revision 1.48 1994/10/25 05:46:11 geoff
- * Fix a couple of places where ifdefs were omitted, though apparently
- * harmlessly.
- *
- * Revision 1.47 1994/09/01 06:06:32 geoff
- * Change erasechar/killchar to uerasechar/ukillchar to avoid
- * shared-library problems on HP systems.
- *
- * Revision 1.46 1994/01/25 07:12:11 geoff
- * Get rid of all old RCS log lines in preparation for the 3.1 release.
- *
- */
-
- #include "config.h"
- #include "ispell.h"
- #include "proto.h"
- #include "msgs.h"
- #ifdef USG
- #include <termio.h>
- #else
- #include <sgtty.h>
- #endif
- #include <signal.h>
-
- void erase P ((void));
- void move P ((int row, int col));
- void inverse P ((void));
- void normal P ((void));
- void backup P ((void));
- static int putch P ((int c));
- void terminit P ((void));
- SIGNAL_TYPE done P ((int signo));
- #ifdef SIGTSTP
- static SIGNAL_TYPE onstop P ((int signo));
- #endif /* SIGTSTP */
- void stop P ((void));
- int shellescape P ((char * buf));
- #ifdef USESH
- void shescape P ((char * buf));
- #endif /* USESH */
-
- void erase ()
- {
-
- if (cl)
- tputs (cl, li, putch);
- else
- {
- if (ho)
- tputs (ho, 100, putch);
- else if (cm)
- tputs (tgoto (cm, 0, 0), 100, putch);
- tputs (cd, li, putch);
- }
- }
-
- void move (row, col)
- int row;
- int col;
- {
- tputs (tgoto (cm, col, row), 100, putch);
- }
-
- void inverse ()
- {
- tputs (so, 10, putch);
- }
-
- void normal ()
- {
- tputs (se, 10, putch);
- }
-
- void backup ()
- {
- if (BC)
- tputs (BC, 1, putch);
- else
- (void) putchar ('\b');
- }
-
- static int putch (c)
- int c;
- {
-
- return putchar (c);
- }
-
- #ifdef USG
- static struct termio sbuf;
- static struct termio osbuf;
- #else
- static struct sgttyb sbuf;
- static struct sgttyb osbuf;
- #ifdef TIOCSLTC
- static struct ltchars ltc;
- static struct ltchars oltc;
- #endif
- #endif
- static int termchanged = 0;
- static SIGNAL_TYPE (*oldint) ();
- static SIGNAL_TYPE (*oldterm) ();
- #ifdef SIGTSTP
- static SIGNAL_TYPE (*oldttin) ();
- static SIGNAL_TYPE (*oldttou) ();
- static SIGNAL_TYPE (*oldtstp) ();
- #endif
-
- void terminit ()
- {
- #ifdef TIOCPGRP
- int tpgrp;
- #else
- #ifdef TIOCGPGRP
- int tpgrp;
- #endif
- #endif
- #ifdef TIOCGWINSZ
- struct winsize wsize;
- #endif /* TIOCGWINSZ */
-
- tgetent (termcap, getenv ("TERM"));
- termptr = termstr;
- BC = tgetstr ("bc", &termptr);
- cd = tgetstr ("cd", &termptr);
- cl = tgetstr ("cl", &termptr);
- cm = tgetstr ("cm", &termptr);
- ho = tgetstr ("ho", &termptr);
- nd = tgetstr ("nd", &termptr);
- so = tgetstr ("so", &termptr); /* inverse video on */
- se = tgetstr ("se", &termptr); /* inverse video off */
- if ((sg = tgetnum ("sg")) < 0) /* space taken by so/se */
- sg = 0;
- ti = tgetstr ("ti", &termptr); /* terminal initialization */
- te = tgetstr ("te", &termptr); /* terminal termination */
- co = tgetnum ("co");
- li = tgetnum ("li");
- #ifdef TIOCGWINSZ
- if (ioctl (0, TIOCGWINSZ, (char *) &wsize) >= 0)
- {
- if (wsize.ws_col != 0)
- co = wsize.ws_col;
- if (wsize.ws_row != 0)
- li = wsize.ws_row;
- }
- #endif /* TIOCGWINSZ */
- /*
- * Let the variables "LINES" and "COLUMNS" override the termcap
- * entry. Technically, this is a terminfo-ism, but I think the
- * vast majority of users will find it pretty handy.
- */
- if (getenv ("COLUMNS") != NULL)
- co = atoi (getenv ("COLUMNS"));
- if (getenv ("LINES") != NULL)
- li = atoi (getenv ("LINES"));
- #if MAX_SCREEN_SIZE > 0
- if (li > MAX_SCREEN_SIZE)
- li = MAX_SCREEN_SIZE;
- #endif /* MAX_SCREEN_SIZE > 0 */
- #if MAXCONTEXT == MINCONTEXT
- contextsize = MINCONTEXT;
- #else /* MAXCONTEXT == MINCONTEXT */
- if (contextsize == 0)
- #ifdef CONTEXTROUNDUP
- contextsize = (li * CONTEXTPCT + 99) / 100;
- #else /* CONTEXTROUNDUP */
- contextsize = (li * CONTEXTPCT) / 100;
- #endif /* CONTEXTROUNDUP */
- if (contextsize > MAXCONTEXT)
- contextsize = MAXCONTEXT;
- else if (contextsize < MINCONTEXT)
- contextsize = MINCONTEXT;
- #endif /* MAX_CONTEXT == MIN_CONTEXT */
- /*
- * Insist on 2 lines for the screen header, 2 for blank lines
- * separating areas of the screen, 2 for word choices, and 2 for
- * the minimenu, plus however many are needed for context. If
- * possible, make the context smaller to fit on the screen.
- */
- if (li < contextsize + 8 && contextsize > MINCONTEXT)
- {
- contextsize = li - 8;
- if (contextsize < MINCONTEXT)
- contextsize = MINCONTEXT;
- }
- if (li < MINCONTEXT + 8)
- (void) fprintf (stderr, TERM_C_SMALL_SCREEN, MINCONTEXT + 8);
-
- #ifdef SIGTSTP
- #ifdef TIOCPGRP
- retry:
- #endif /* SIGTSTP */
- #endif /* TIOCPGRP */
-
- #ifdef USG
- if (!isatty (0))
- {
- (void) fprintf (stderr, TERM_C_NO_BATCH);
- exit (1);
- }
- (void) ioctl (0, TCGETA, (char *) &osbuf);
- termchanged = 1;
-
- sbuf = osbuf;
- sbuf.c_lflag &= ~(ECHO | ECHOK | ECHONL | ICANON);
- sbuf.c_oflag &= ~(OPOST);
- sbuf.c_iflag &= ~(INLCR | IGNCR | ICRNL);
- sbuf.c_cc[VMIN] = 1;
- sbuf.c_cc[VTIME] = 1;
- (void) ioctl (0, TCSETAW, (char *) &sbuf);
-
- uerasechar = osbuf.c_cc[VERASE];
- ukillchar = osbuf.c_cc[VKILL];
-
- #endif
-
- #ifdef SIGTSTP
- #ifndef USG
- (void) sigsetmask (1<<(SIGTSTP-1) | 1<<(SIGTTIN-1) | 1<<(SIGTTOU-1));
- #endif
- #endif
- #ifdef TIOCGPGRP
- if (ioctl (0, TIOCGPGRP, (char *) &tpgrp) != 0)
- {
- (void) fprintf (stderr, TERM_C_NO_BATCH);
- exit (1);
- }
- #endif
- #ifdef SIGTSTP
- #ifdef TIOCPGRP
- if (tpgrp != getpgrp(0)) /* not in foreground */
- {
- #ifndef USG
- (void) sigsetmask (1 << (SIGTSTP - 1) | 1 << (SIGTTIN - 1));
- #endif
- (void) signal (SIGTTOU, SIG_DFL);
- (void) kill (0, SIGTTOU);
- /* job stops here waiting for SIGCONT */
- goto retry;
- }
- #endif
- #endif
-
- #ifndef USG
- (void) ioctl (0, TIOCGETP, (char *) &osbuf);
- #ifdef TIOCGLTC
- (void) ioctl (0, TIOCGLTC, (char *) &oltc);
- #endif
- termchanged = 1;
-
- sbuf = osbuf;
- sbuf.sg_flags &= ~ECHO;
- sbuf.sg_flags |= TERM_MODE;
- (void) ioctl (0, TIOCSETP, (char *) &sbuf);
-
- uerasechar = sbuf.sg_erase;
- ukillchar = sbuf.sg_kill;
-
- #ifdef TIOCSLTC
- ltc = oltc;
- ltc.t_suspc = -1;
- (void) ioctl (0, TIOCSLTC, (char *) <c);
- #endif
-
- #endif /* USG */
-
- if ((oldint = signal (SIGINT, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGINT, done);
- if ((oldterm = signal (SIGTERM, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGTERM, done);
-
- #ifdef SIGTSTP
- #ifndef USG
- (void) sigsetmask (0);
- #endif
- if ((oldttin = signal (SIGTTIN, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGTTIN, onstop);
- if ((oldttou = signal (SIGTTOU, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGTTOU, onstop);
- if ((oldtstp = signal (SIGTSTP, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGTSTP, onstop);
- #endif
- if (ti)
- tputs (ti, 1, putch);
- }
-
- /* ARGSUSED */
- SIGNAL_TYPE done (signo)
- int signo;
- {
- if (tempfile[0] != '\0')
- (void) unlink (tempfile);
- if (termchanged)
- {
- if (te)
- tputs (te, 1, putch);
- #ifdef USG
- (void) ioctl (0, TCSETAW, (char *) &osbuf);
- #else
- (void) ioctl (0, TIOCSETP, (char *) &osbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, (char *) &oltc);
- #endif
- #endif
- }
- exit (0);
- }
-
- #ifdef SIGTSTP
- static SIGNAL_TYPE onstop (signo)
- int signo;
- {
- #ifdef USG
- (void) ioctl (0, TCSETAW, (char *) &osbuf);
- #else
- (void) ioctl (0, TIOCSETP, (char *) &osbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, (char *) &oltc);
- #endif
- #endif
- (void) signal (signo, SIG_DFL);
- #ifndef USG
- (void) sigsetmask (sigblock (0) & ~(1 << (signo - 1)));
- #endif
- (void) kill (0, signo);
- /* stop here until continued */
- (void) signal (signo, onstop);
- #ifdef USG
- (void) ioctl (0, TCSETAW, (char *) &sbuf);
- #else
- (void) ioctl (0, TIOCSETP, (char *) &sbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, (char *) <c);
- #endif
- #endif
- }
- #endif
-
- void stop ()
- {
- #ifdef SIGTSTP
- onstop (SIGTSTP);
- #else
- /* for System V */
- move (li - 1, 0);
- (void) fflush (stdout);
- if (getenv ("SHELL"))
- (void) shellescape (getenv ("SHELL"));
- else
- (void) shellescape ("sh");
- #endif
- }
-
- /* Fork and exec a process. Returns NZ if command found, regardless of
- ** command's return status. Returns zero if command was not found.
- ** Doesn't use a shell.
- */
- #ifndef USESH
- #define NEED_SHELLESCAPE
- #endif /* USESH */
- #ifndef REGEX_LOOKUP
- #define NEED_SHELLESCAPE
- #endif /* REGEX_LOOKUP */
- #ifdef NEED_SHELLESCAPE
- int shellescape (buf)
- char * buf;
- {
- char * argv[100];
- char * cp = buf;
- int i = 0;
- int termstat;
-
- /* parse buf to args (destroying it in the process) */
- while (*cp != '\0')
- {
- while (*cp == ' ' || *cp == '\t')
- ++cp;
- if (*cp == '\0')
- break;
- argv[i++] = cp;
- while (*cp != ' ' && *cp != '\t' && *cp != '\0')
- ++cp;
- if (*cp != '\0')
- *cp++ = '\0';
- }
- argv[i] = NULL;
-
- #ifdef USG
- (void) ioctl (0, TCSETAW, (char *) &osbuf);
- #else
- (void) ioctl (0, TIOCSETP, (char *) &osbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, (char *) &oltc);
- #endif /* TIOCSLTC */
- #endif
- (void) signal (SIGINT, oldint);
- (void) signal (SIGTERM, oldterm);
- #ifdef SIGTSTP
- (void) signal (SIGTTIN, oldttin);
- (void) signal (SIGTTOU, oldttou);
- (void) signal (SIGTSTP, oldtstp);
- #endif
- if ((i = fork ()) == 0)
- {
- (void) execvp (argv[0], (char **) argv);
- _exit (123); /* Command not found */
- }
- else if (i > 0)
- {
- while (wait (&termstat) != i)
- ;
- termstat = (termstat == (123 << 8)) ? 0 : -1;
- }
- else
- {
- (void) printf (TERM_C_CANT_FORK);
- termstat = -1; /* Couldn't fork */
- }
-
- if (oldint != SIG_IGN)
- (void) signal (SIGINT, done);
- if (oldterm != SIG_IGN)
- (void) signal (SIGTERM, done);
-
- #ifdef SIGTSTP
- if (oldttin != SIG_IGN)
- (void) signal (SIGTTIN, onstop);
- if (oldttou != SIG_IGN)
- (void) signal (SIGTTOU, onstop);
- if (oldtstp != SIG_IGN)
- (void) signal (SIGTSTP, onstop);
- #endif
-
- #ifdef USG
- (void) ioctl (0, TCSETAW, (char *) &sbuf);
- #else
- (void) ioctl (0, TIOCSETP, (char *) &sbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, (char *) <c);
- #endif /* TIOCSLTC */
- #endif
- if (termstat)
- {
- (void) printf (TERM_C_TYPE_SPACE);
- (void) fflush (stdout);
- #ifdef COMMANDFORSPACE
- i = GETKEYSTROKE ();
- if (i != ' ' && i != '\n' && i != '\r')
- (void) ungetc (i, stdin);
- #else
- while (GETKEYSTROKE () != ' ')
- ;
- #endif
- }
- return (termstat);
- }
- #endif /* NEED_SHELLESCAPE */
-
- #ifdef USESH
- void shescape (buf)
- char * buf;
- {
- #ifdef COMMANDFORSPACE
- int ch;
- #endif
-
- #ifdef USG
- (void) ioctl (0, TCSETAW, (char *) &osbuf);
- #else
- (void) ioctl (0, TIOCSETP, (char *) &osbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, (char *) &oltc);
- #endif
- #endif
- (void) signal (SIGINT, oldint);
- (void) signal (SIGTERM, oldterm);
- #ifdef SIGTSTP
- (void) signal (SIGTTIN, oldttin);
- (void) signal (SIGTTOU, oldttou);
- (void) signal (SIGTSTP, oldtstp);
- #endif
-
- (void) system (buf);
-
- if (oldint != SIG_IGN)
- (void) signal (SIGINT, done);
- if (oldterm != SIG_IGN)
- (void) signal (SIGTERM, done);
-
- #ifdef SIGTSTP
- if (oldttin != SIG_IGN)
- (void) signal (SIGTTIN, onstop);
- if (oldttou != SIG_IGN)
- (void) signal (SIGTTOU, onstop);
- if (oldtstp != SIG_IGN)
- (void) signal (SIGTSTP, onstop);
- #endif
-
- #ifdef USG
- (void) ioctl (0, TCSETAW, (char *) &sbuf);
- #else
- (void) ioctl (0, TIOCSETP, (char *) &sbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, (char *) <c);
- #endif
- #endif
- (void) printf (TERM_C_TYPE_SPACE);
- (void) fflush (stdout);
- #ifdef COMMANDFORSPACE
- ch = GETKEYSTROKE ();
- if (ch != ' ' && ch != '\n' && ch != '\r')
- (void) ungetc (ch, stdin);
- #else
- while (GETKEYSTROKE () != ' ')
- ;
- #endif
- }
- #endif
-